<!--
 * @Author: jhw
 * @Date: 2025-08-13 10:55:02
 * @LastEditors: jhw
 * @LastEditTime: 2025-08-22 16:57:34
 * @Description:
-->
<template>
  <div class="quiz-container w-800px mx-auto">
    <div class="mt-30px mb-20px">题目数量：{{ store.questionCount }}</div>
    <div
      class="content mb-16px"
      v-for="(com, index) in coms"
      :key="index"
      :ref="(el) => (componentRefs[index] = el as HTMLElement)"
    >
      <component
        :is="com.type"
        :status="com.status"
        :componentId="com.id"
        :serialNum="serialNum[index]"
        @updateAnswer="updateAnswer(index, $event)"
      />
    </div>
    <div class="mt-20px mb-20px text-center">
      <el-button type="primary" @click="submitAnswers">提交答案</el-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { getSurveyBySurveyId, submitSurveyAnswer } from '@/api';
import { useEditorStore } from '@/stores/useEditor';
import { restoreSurvey } from '@/utils/effect';
import { useSerialNum, useTime } from '@/utils/hooks';
import { computed, onMounted, ref, nextTick, onBeforeUnmount } from 'vue';
import { useRoute } from 'vue-router';
import { getCurrentStatus, getTextStatus } from '@/utils';
import type { OptionsProps, TextProps } from '@/types';
import { formatDate, formatDuration } from '@/utils/common';
import { ElMessage } from 'element-plus';

const store = useEditorStore();
const route = useRoute();
const { startTime, endTime, totalDuration, isAnswering, startAnswering, endAnswering } = useTime();
const id = route.params.id as string;
const coms = computed(() => store.coms);
const serialNum = computed(() => useSerialNum(coms.value).value);

// 存储用户答案
const userAnswers = new Map<number, any>();
// 组件引用数组，用于滚动定位
const componentRefs = ref<(HTMLElement | null)[]>([]);

// 监听页面卸载（用户关闭页面）
const handleBeforeUnload = () => {
  if (isAnswering.value) {
    endAnswering();
  }
};

const updateAnswer = (
  index: number,
  answer: { serialNum: number; answer: string; title: string },
) => {
  console.log(index, answer);
  // 存储答案
  userAnswers.set(index, answer);
};

// 滚动到指定组件
const scrollToComponent = (index: number) => {
  nextTick(() => {
    const element = componentRefs.value[index];
    if (element) {
      element.scrollIntoView({
        behavior: 'smooth',
        block: 'center',
      });

      // 添加高亮效果
      element.classList.add('highlight-error');
      setTimeout(() => {
        element.classList.remove('highlight-error');
      }, 3000);
    }
  });
};

// 校验必答题是否已填写
const validateRequiredQuestions = () => {
  const errors: string[] = [];
  let firstErrorIndex = -1;

  coms.value.forEach((com, index) => {
    // 跳过非问题组件（如标题描述组件）
    if (com.name === 'note-desc') {
      return;
    }

    // 检查是否为必答题
    const isRequire = com.status.isRequire
      ? getCurrentStatus(com.status.isRequire as OptionsProps)
      : 0;

    if (isRequire === 1) {
      // 必答题
      const answer = userAnswers.get(index);
      const title = com.status.title
        ? getTextStatus(com.status.title as TextProps)
        : `第${index + 1}题`;

      // 根据组件类型进行不同的校验
      if (!answer || !isAnswerValid(answer.answer, com.name)) {
        errors.push(`请填写必答题：${title}`);
        // 记录第一个错误的索引
        if (firstErrorIndex === -1) {
          firstErrorIndex = index;
        }
      }
    }
  });

  return { errors, firstErrorIndex };
};

// 根据组件类型校验答案是否有效
const isAnswerValid = (answer: any, componentName: string): boolean => {
  if (answer === null || answer === undefined) {
    return false;
  }

  switch (componentName) {
    case 'text-input':
      return typeof answer === 'string' && answer.trim() !== '';

    case 'single-select':
    case 'option-select':
    case 'personal-info-gender':
    case 'personal-info-education':
    case 'date-time':
    case 'single-pic-select':
      return typeof answer === 'string' && answer !== '';

    case 'multiple-select':
      return Array.isArray(answer) && answer.length > 0;

    case 'personal-info-score':
      return typeof answer === 'number' && answer > 0;

    default:
      return true;
  }
};

const submitAnswers = async () => {
  // 对必答题进行校验
  const { errors, firstErrorIndex } = validateRequiredQuestions();

  if (errors.length > 0) {
    // 滚动到第一个未填写的必答题
    if (firstErrorIndex !== -1) {
      scrollToComponent(firstErrorIndex);
    }
    return;
  }

  // 结束答题计时
  endAnswering();

  // 校验通过，可以提交答案
  const answersArray = Array.from(userAnswers.values());
  console.log('提交的答案：', answersArray);
  const reqObj = {
    surveyId: id,
    answers: answersArray,
    userId: Math.random().toString(36).substring(2, 15),
    // 已答题数量
    answeredCount: answersArray.length,
    // 总题数
    totalCount: store.questionCount,
    // 答题时间相关数据
    startTime: formatDate(startTime.value?.getTime() || 0),
    endTime: formatDate(endTime.value?.getTime() || 0),
    totalDuration: totalDuration.value,
    durationFormatted: formatDuration(totalDuration.value),
  };
  console.log('reqObj', reqObj);
  const { code, data } = await submitSurveyAnswer(reqObj);
  if (code === 200 && data) {
    ElMessage.success('提交答案成功');
    setTimeout(() => {
      window.close();
    }, 1000);
  } else {
    ElMessage.error('提交答案失败');
  }
};

const getSurvey = async () => {
  if (!id) return;
  const { code, data } = await getSurveyBySurveyId(id);
  if (code === 200) {
    restoreSurvey(data.components);
    store.setComs(data);

    // 开始新的答题
    startAnswering();
  }
};

onMounted(() => {
  getSurvey();

  // 添加事件监听器
  window.addEventListener('beforeunload', handleBeforeUnload); // 监听页面卸载
});

onBeforeUnmount(() => {
  // 清理事件监听器
  window.removeEventListener('beforeunload', handleBeforeUnload);

  // 如果还在答题中，结束计时
  if (isAnswering.value) {
    endAnswering();
  }
});
</script>

<style scoped>
/* 错误高亮效果 */
.highlight-error {
  animation: shake 0.5s ease-in-out;
  border: 2px solid #f56c6c !important;
  border-radius: 8px;
  background-color: rgba(245, 108, 108, 0.1);
}

@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  75% {
    transform: translateX(5px);
  }
}

/* 确保内容区域有足够的间距 */
.content {
  padding: 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  transition: all 0.3s ease;
}
</style>
